Introduction

Trying to calculate housing stress using 30/40 as in here: https://www.ahuri.edu.au/policy/ahuri-briefs/2016/3040-indicator

2016 Census - Counting Dwellings, Place of Enumeration (SA2)

Data Source: Census of Population and Housing, 2016, TableBuilder

Counting: Dwellings Location on Census Night

Variables:

library(tidyverse)
library(readxl)
library(sf)
library(tmap)
library(janitor)
library(scales)

Importing the raw data

##original files - 2016 census data - csv string - zeros suppressed
rentdata <- read_csv("sa2_hied_rntrd_2gmel_ zeros_suppressed.csv", skip = 10) %>% 
  filter(GCCSA == "Greater Melbourne") %>% # gets rid of the rows at the end
  select(-X7) #removes the last column
Missing column names filled in: 'X7' [7]Parsed with column specification:
cols(
  Counting = col_character(),
  GCCSA = col_character(),
  SA2 = col_character(),
  `HIED Equivalised Total Household Income (weekly)` = col_character(),
  `RNTRD Rent (weekly) Ranges` = col_character(),
  Count = col_double(),
  X7 = col_character()
)
49099 parsing failures.
row col  expected    actual                                         file
  1  -- 7 columns 6 columns 'sa2_hied_rntrd_2gmel_ zeros_suppressed.csv'
  2  -- 7 columns 6 columns 'sa2_hied_rntrd_2gmel_ zeros_suppressed.csv'
  3  -- 7 columns 6 columns 'sa2_hied_rntrd_2gmel_ zeros_suppressed.csv'
  4  -- 7 columns 6 columns 'sa2_hied_rntrd_2gmel_ zeros_suppressed.csv'
  5  -- 7 columns 6 columns 'sa2_hied_rntrd_2gmel_ zeros_suppressed.csv'
... ... ......... ......... ............................................
See problems(...) for more details.
mortdata <- read_csv("sa2_hied_mrerd_2gmel_ zeros_suppressed.csv", skip = 10) %>% 
  filter(GCCSA == "Greater Melbourne") %>% # gets rid of the rows at the end
  select(-X7) #removes the last column
Missing column names filled in: 'X7' [7]Parsed with column specification:
cols(
  Counting = col_character(),
  GCCSA = col_character(),
  SA2 = col_character(),
  `HIED Equivalised Total Household Income (weekly)` = col_character(),
  `MRERD Mortgage Repayments (monthly) Ranges` = col_character(),
  Count = col_double(),
  X7 = col_character()
)

|=====                                                                                                |   5%
|========                                                                                             |   8%
|===========                                                                                          |  11%
|=============                                                                                        |  13%
|===============                                                                              |  16%    1 MB
|==================                                                                           |  19%    1 MB
|====================                                                                         |  22%    1 MB
|=======================                                                                      |  25%    1 MB
|==========================                                                                   |  27%    1 MB
|============================                                                                 |  30%    2 MB
|===============================                                                              |  33%    2 MB
|==================================                                                           |  36%    2 MB
|====================================                                                         |  39%    2 MB
|=======================================                                                      |  41%    2 MB
|=========================================                                                    |  44%    3 MB
|============================================                                                 |  47%    3 MB
|===============================================                                              |  50%    3 MB
|=================================================                                            |  53%    3 MB
|====================================================                                         |  55%    3 MB
|=======================================================                                      |  58%    4 MB
|=========================================================                                    |  61%    4 MB
|============================================================                                 |  64%    4 MB
|===============================================================                              |  67%    4 MB
|=================================================================                            |  70%    4 MB
|====================================================================                         |  72%    5 MB
|=======================================================================                      |  75%    5 MB
|=========================================================================                    |  78%    5 MB
|============================================================================                 |  81%    5 MB
|==============================================================================               |  83%    5 MB
|=================================================================================            |  86%    6 MB
|====================================================================================         |  89%    6 MB
|======================================================================================       |  92%    6 MB
|=========================================================================================    |  95%    6 MB
|===========================================================================================  |  97%    6 MB
|==============================================================================================| 100%    7 MB
59701 parsing failures.
row col  expected    actual                                         file
  1  -- 7 columns 6 columns 'sa2_hied_mrerd_2gmel_ zeros_suppressed.csv'
  2  -- 7 columns 6 columns 'sa2_hied_mrerd_2gmel_ zeros_suppressed.csv'
  3  -- 7 columns 6 columns 'sa2_hied_mrerd_2gmel_ zeros_suppressed.csv'
  4  -- 7 columns 6 columns 'sa2_hied_mrerd_2gmel_ zeros_suppressed.csv'
  5  -- 7 columns 6 columns 'sa2_hied_mrerd_2gmel_ zeros_suppressed.csv'
... ... ......... ......... ............................................
See problems(...) for more details.

Transforming the rent data

rent <- rentdata %>% 
  rename(sa2 = SA2) %>% 
  rename(hhincwk = `HIED Equivalised Total Household Income (weekly)`) %>% 
  rename(rentwk = `RNTRD Rent (weekly) Ranges`) %>% 
  mutate(hhincwk = as_factor(hhincwk), rentwk = as_factor(rentwk)) %>% 
  rename(hh = Count) %>% 
  select(-Counting)
rent
rent_dw <- rent %>%
  filter(hhincwk != 'Not applicable') %>% 
  filter(rentwk != 'Not applicable') %>% 
  group_by(sa2) %>% 
  summarise(dw = sum(hh)) 
rent_dw #improve this by just getting the dwelling data from the datapacks and joining them on at the end -G32
rent_hh <- rent %>% 
  filter(!hhincwk %in% c('Nil income', 'Partial income stated', 'All incomes not stated', 'Not applicable')) %>% 
  filter(!rentwk %in% c('Not stated', 'Not applicable' ))
rent_hh

Transforming the mortgage data

mort <- mortdata %>% 
  rename(sa2 = SA2) %>% 
  rename(hhincwk = `HIED Equivalised Total Household Income (weekly)`) %>% 
  rename(mortmth = `MRERD Mortgage Repayments (monthly) Ranges`) %>% 
  mutate(hhincwk = as_factor(hhincwk), mortmth = as_factor(mortmth)) %>% 
  rename(hh = Count) %>% 
  select(-Counting)
mort
mort_dw <- mort %>% 
  filter(hhincwk != 'Not applicable') %>% 
  filter(mortmth != 'Not applicable') %>% 
  group_by(sa2) %>% 
  summarise(dw = sum(hh)) 
mort_dw #as noted above
mort_hh <- mort %>% 
  filter(!hhincwk %in% c('Nil income', 'Partial income stated', 'All incomes not stated', 'Not applicable')) %>% 
  filter(!mortmth %in% c('Not stated', 'Not applicable'))
mort_hh

Midpoints for income

hhincwk_mid <- rentdata %>% 
  rename(sa2 = SA2) %>% 
  rename(hhincwk = `HIED Equivalised Total Household Income (weekly)`) %>% 
  mutate(hhincwk = as_factor(hhincwk)) %>% 
  distinct(hhincwk) %>% 
  filter(!hhincwk %in% c('Nil income', 'Partial income stated', 'All incomes not stated', 'Not applicable', 'Total')) %>% 
  mutate(inc_low = c(1, 150, 300, 400, 500, 650, 800, 1000, 1250, 1500, 1750, 2000, 2500, 3000)) %>% 
  mutate(inc_high = c(149, 299, 399, 499, 649, 799, 999, 1249, 1499, 1749, 1999, 2499, 2999, 3499)) %>% 
  mutate(inc_mid = (inc_low+inc_high)/2) %>% 
  select(hhincwk, inc_mid)
hhincwk_mid 

Filter to include only bottom 40 per cent of households by income

Equivalised disposable household income - P40 = $714 in 2015-16 for VIC - http://www.abs.gov.au/AUSSTATS/abs@.nsf/DetailsPage/6523.02015-16?OpenDocument

hhincwk_mid40 <- hhincwk_mid %>% 
  filter(inc_mid <= 714)
hhincwk_mid40

Midpoints for rent and mortgages

rentwk_mid <- rentdata %>% 
  rename(rentwk = `RNTRD Rent (weekly) Ranges`) %>% 
  distinct(rentwk) %>% 
  mutate(rentwk = as_factor(rentwk)) %>% 
  filter(!rentwk %in% c('Not stated', 'Not applicable', 'Total' )) %>% 
  mutate(rent_low = c(0, 1, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300, 325, 350, 375, 400, 425, 450, 550, 650, 750, 850, 950)) %>% 
  mutate(rent_high = c(0, 74, 99, 124, 149, 174, 199, 224, 249, 274, 299, 324, 349, 374, 399, 424, 449, 549, 649, 749, 849, 949, 1050)) %>% 
  mutate(rent_mid = (rent_low + rent_high)/2) %>% 
  select(rentwk, rent_mid)
rentwk_mid
mortwk_mid <- mortdata %>% 
  rename(mortmth = `MRERD Mortgage Repayments (monthly) Ranges`) %>% 
  distinct(mortmth) %>% 
  mutate(mortmth = as_factor(mortmth)) %>% 
  filter(!mortmth %in% c('Not stated', 'Not applicable')) %>% 
  mutate(mort_low = c(0, 1, 150, 300, 450, 600, 800, 1000, 1200, 1400, 1600, 1800, 2000, 2200, 2400, 2600, 3000, 4000, 5000)) %>%
  mutate(mortwk_low = mort_low/4) %>% 
  mutate(mort_high = c(0, 149, 299, 449, 599, 799, 999, 1199, 1399, 1599, 1799, 1999, 2199, 2399, 2599, 2999, 3999, 4999, 5999)) %>% 
  mutate(mortwk_high = mort_high/4) %>% 
  mutate(mort_mid = (mort_low + mort_high)/2) %>% 
  mutate(mortwk_mid = (mortwk_low + mortwk_high)/2) %>% 
  select(mortmth, mort_mid, mortwk_mid)
mortwk_mid 

Joining

#joining the data  ####
rent_join <- left_join(hhincwk_mid40, rent_hh)
Joining, by = "hhincwk"
rent_join <- left_join(rent_join, rentwk_mid)
Joining, by = "rentwk"
rent_join
mort_join <- left_join(hhincwk_mid40, mort_hh)
Joining, by = "hhincwk"
mort_join <- left_join(mort_join, mortwk_mid)
Joining, by = "mortmth"
mort_join

Stress

rentalstress <- rent_join %>% 
  mutate(prophousing = rent_mid/inc_mid) %>% 
  mutate(hstress = ifelse(prophousing <= 0.3, 0, hh)) %>% 
  group_by(sa2) %>% 
  summarise(lowinc_hh = sum(hh), hstress = sum(hstress))
rentalstress <- left_join(rentalstress, rent_dw, by = "sa2") %>% 
  select(sa2, dw, lowinc_hh, hstress) %>% 
  mutate(propstress = hstress/dw)
rentalstress
mortgagestress <- mort_join %>% 
  mutate(prophousing = mortwk_mid/inc_mid) %>% 
  mutate(hstress = ifelse(prophousing <= 0.3, 0, hh)) %>% 
  group_by(sa2) %>% 
  summarise(lowinc_hh = sum(hh), hstress = sum(hstress))
mortgagestress <- left_join(mortgagestress, mort_dw, by = "sa2") %>% 
  select(sa2, dw, lowinc_hh, hstress) %>% 
  mutate(propstress = hstress/dw)
mortgagestress 
housingstress_join <- full_join(rentalstress, mortgagestress)
Joining, by = c("sa2", "dw", "lowinc_hh", "hstress", "propstress")
housingstress_sa2 <- housingstress_join %>% 
  group_by(sa2) %>% 
  summarise(dw = sum(dw), lowinc_hh = sum(lowinc_hh), hstress = sum(hstress)) %>% 
  mutate(prop_stress = hstress/dw) %>% 
  filter(!is.na(prop_stress))
housingstress_sa2
write_csv(housingstress_sa2, "tables_out/housingstress_sa2.csv")

The shapefile

gm_shp <- st_read("shp/SA2_2016_GMEL.shp") %>% 
  clean_names() %>% 
  select(sa2_name16) %>% 
  left_join(housingstress_sa2, by = c("sa2_name16" = "sa2")) %>% 
  mutate(prop_stress = round(prop_stress, 2))
Reading layer `SA2_2016_GMEL' from data source `C:\Users\willi\Desktop\R\HousingAffordabilityData_2016Census\shp\SA2_2016_GMEL.shp' using driver `ESRI Shapefile'
Simple feature collection with 309 features and 12 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: 144.3336 ymin: -38.50299 xmax: 145.8784 ymax: -37.1751
epsg (SRID):    NA
proj4string:    +proj=longlat +ellps=GRS80 +no_defs
Column `sa2_name16`/`sa2` joining factor and character vector, coercing into character vector

The map

tmap_mode("view")
tmap mode set to interactive viewing
tm_shape(gm_shp) +
  tm_polygons("prop_stress")
LS0tDQp0aXRsZTogIkhvdXNpbmcgU3RyZXNzIC0gU0EycyBpbiBHcmVhdGVyIE1lbGJvdXJuZSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiNJbnRyb2R1Y3Rpb24NCg0KVHJ5aW5nIHRvIGNhbGN1bGF0ZSBob3VzaW5nIHN0cmVzcyB1c2luZyAzMC80MCBhcyBpbiBoZXJlOiAgaHR0cHM6Ly93d3cuYWh1cmkuZWR1LmF1L3BvbGljeS9haHVyaS1icmllZnMvMjAxNi8zMDQwLWluZGljYXRvciANCg0KMjAxNiBDZW5zdXMgLSBDb3VudGluZyBEd2VsbGluZ3MsIFBsYWNlIG9mIEVudW1lcmF0aW9uIChTQTIpDQoNCkRhdGEgU291cmNlOiBDZW5zdXMgb2YgUG9wdWxhdGlvbiBhbmQgSG91c2luZywgMjAxNiwgVGFibGVCdWlsZGVyDQoNCkNvdW50aW5nOiBEd2VsbGluZ3MgTG9jYXRpb24gb24gQ2Vuc3VzIE5pZ2h0DQoNClZhcmlhYmxlczoNCg0KKiBISUVEIEVxdWl2YWxpc2VkIFRvdGFsIEhvdXNlaG9sZCBJbmNvbWUgKHdlZWtseSkNCiogUk5UUkQgUmVudCAod2Vla2x5KSBSYW5nZXMNCiogTVJFUkQgTW9ydGdhZ2UgUmVwYXltZW50cyAobW9udGhseSkgUmFuZ2VzDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlID0gRkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShzZikNCmxpYnJhcnkodG1hcCkNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkoc2NhbGVzKQ0KYGBgDQoNCiMjSW1wb3J0aW5nIHRoZSByYXcgZGF0YQ0KDQpgYGB7cn0NCiMjb3JpZ2luYWwgZmlsZXMgLSAyMDE2IGNlbnN1cyBkYXRhIC0gY3N2IHN0cmluZyAtIHplcm9zIHN1cHByZXNzZWQNCnJlbnRkYXRhIDwtIHJlYWRfY3N2KCJzYTJfaGllZF9ybnRyZF8yZ21lbF8gemVyb3Nfc3VwcHJlc3NlZC5jc3YiLCBza2lwID0gMTApICU+JSANCiAgZmlsdGVyKEdDQ1NBID09ICJHcmVhdGVyIE1lbGJvdXJuZSIpICU+JSAjIGdldHMgcmlkIG9mIHRoZSByb3dzIGF0IHRoZSBlbmQNCiAgc2VsZWN0KC1YNykgI3JlbW92ZXMgdGhlIGxhc3QgY29sdW1uDQoNCm1vcnRkYXRhIDwtIHJlYWRfY3N2KCJzYTJfaGllZF9tcmVyZF8yZ21lbF8gemVyb3Nfc3VwcHJlc3NlZC5jc3YiLCBza2lwID0gMTApICU+JSANCiAgZmlsdGVyKEdDQ1NBID09ICJHcmVhdGVyIE1lbGJvdXJuZSIpICU+JSAjIGdldHMgcmlkIG9mIHRoZSByb3dzIGF0IHRoZSBlbmQNCiAgc2VsZWN0KC1YNykgI3JlbW92ZXMgdGhlIGxhc3QgY29sdW1uDQpgYGANCg0KIyNUcmFuc2Zvcm1pbmcgdGhlIHJlbnQgZGF0YQ0KDQpgYGB7cn0NCnJlbnQgPC0gcmVudGRhdGEgJT4lIA0KICByZW5hbWUoc2EyID0gU0EyKSAlPiUgDQogIHJlbmFtZShoaGluY3drID0gYEhJRUQgRXF1aXZhbGlzZWQgVG90YWwgSG91c2Vob2xkIEluY29tZSAod2Vla2x5KWApICU+JSANCiAgcmVuYW1lKHJlbnR3ayA9IGBSTlRSRCBSZW50ICh3ZWVrbHkpIFJhbmdlc2ApICU+JSANCiAgbXV0YXRlKGhoaW5jd2sgPSBhc19mYWN0b3IoaGhpbmN3ayksIHJlbnR3ayA9IGFzX2ZhY3RvcihyZW50d2spKSAlPiUgDQogIHJlbmFtZShoaCA9IENvdW50KSAlPiUgDQogIHNlbGVjdCgtQ291bnRpbmcpDQpyZW50DQoNCnJlbnRfZHcgPC0gcmVudCAlPiUNCiAgZmlsdGVyKGhoaW5jd2sgIT0gJ05vdCBhcHBsaWNhYmxlJykgJT4lIA0KICBmaWx0ZXIocmVudHdrICE9ICdOb3QgYXBwbGljYWJsZScpICU+JSANCiAgZ3JvdXBfYnkoc2EyKSAlPiUgDQogIHN1bW1hcmlzZShkdyA9IHN1bShoaCkpIA0KcmVudF9kdyAjaW1wcm92ZSB0aGlzIGJ5IGp1c3QgZ2V0dGluZyB0aGUgZHdlbGxpbmcgZGF0YSBmcm9tIHRoZSBkYXRhcGFja3MgYW5kIGpvaW5pbmcgdGhlbSBvbiBhdCB0aGUgZW5kIC1HMzINCg0KcmVudF9oaCA8LSByZW50ICU+JSANCiAgZmlsdGVyKCFoaGluY3drICVpbiUgYygnTmlsIGluY29tZScsICdQYXJ0aWFsIGluY29tZSBzdGF0ZWQnLCAnQWxsIGluY29tZXMgbm90IHN0YXRlZCcsICdOb3QgYXBwbGljYWJsZScpKSAlPiUgDQogIGZpbHRlcighcmVudHdrICVpbiUgYygnTm90IHN0YXRlZCcsICdOb3QgYXBwbGljYWJsZScgKSkNCnJlbnRfaGgNCmBgYA0KDQojI1RyYW5zZm9ybWluZyB0aGUgbW9ydGdhZ2UgZGF0YQ0KDQpgYGB7cn0NCm1vcnQgPC0gbW9ydGRhdGEgJT4lIA0KICByZW5hbWUoc2EyID0gU0EyKSAlPiUgDQogIHJlbmFtZShoaGluY3drID0gYEhJRUQgRXF1aXZhbGlzZWQgVG90YWwgSG91c2Vob2xkIEluY29tZSAod2Vla2x5KWApICU+JSANCiAgcmVuYW1lKG1vcnRtdGggPSBgTVJFUkQgTW9ydGdhZ2UgUmVwYXltZW50cyAobW9udGhseSkgUmFuZ2VzYCkgJT4lIA0KICBtdXRhdGUoaGhpbmN3ayA9IGFzX2ZhY3RvcihoaGluY3drKSwgbW9ydG10aCA9IGFzX2ZhY3Rvcihtb3J0bXRoKSkgJT4lIA0KICByZW5hbWUoaGggPSBDb3VudCkgJT4lIA0KICBzZWxlY3QoLUNvdW50aW5nKQ0KbW9ydA0KDQptb3J0X2R3IDwtIG1vcnQgJT4lIA0KICBmaWx0ZXIoaGhpbmN3ayAhPSAnTm90IGFwcGxpY2FibGUnKSAlPiUgDQogIGZpbHRlcihtb3J0bXRoICE9ICdOb3QgYXBwbGljYWJsZScpICU+JSANCiAgZ3JvdXBfYnkoc2EyKSAlPiUgDQogIHN1bW1hcmlzZShkdyA9IHN1bShoaCkpIA0KbW9ydF9kdyAjYXMgbm90ZWQgYWJvdmUNCg0KbW9ydF9oaCA8LSBtb3J0ICU+JSANCiAgZmlsdGVyKCFoaGluY3drICVpbiUgYygnTmlsIGluY29tZScsICdQYXJ0aWFsIGluY29tZSBzdGF0ZWQnLCAnQWxsIGluY29tZXMgbm90IHN0YXRlZCcsICdOb3QgYXBwbGljYWJsZScpKSAlPiUgDQogIGZpbHRlcighbW9ydG10aCAlaW4lIGMoJ05vdCBzdGF0ZWQnLCAnTm90IGFwcGxpY2FibGUnKSkNCm1vcnRfaGgNCmBgYA0KDQojI01pZHBvaW50cyBmb3IgaW5jb21lDQoNCmBgYHtyfQ0KaGhpbmN3a19taWQgPC0gcmVudGRhdGEgJT4lIA0KICByZW5hbWUoc2EyID0gU0EyKSAlPiUgDQogIHJlbmFtZShoaGluY3drID0gYEhJRUQgRXF1aXZhbGlzZWQgVG90YWwgSG91c2Vob2xkIEluY29tZSAod2Vla2x5KWApICU+JSANCiAgbXV0YXRlKGhoaW5jd2sgPSBhc19mYWN0b3IoaGhpbmN3aykpICU+JSANCiAgZGlzdGluY3QoaGhpbmN3aykgJT4lIA0KICBmaWx0ZXIoIWhoaW5jd2sgJWluJSBjKCdOaWwgaW5jb21lJywgJ1BhcnRpYWwgaW5jb21lIHN0YXRlZCcsICdBbGwgaW5jb21lcyBub3Qgc3RhdGVkJywgJ05vdCBhcHBsaWNhYmxlJywgJ1RvdGFsJykpICU+JSANCiAgbXV0YXRlKGluY19sb3cgPSBjKDEsIDE1MCwgMzAwLCA0MDAsIDUwMCwgNjUwLCA4MDAsIDEwMDAsIDEyNTAsIDE1MDAsIDE3NTAsIDIwMDAsIDI1MDAsIDMwMDApKSAlPiUgDQogIG11dGF0ZShpbmNfaGlnaCA9IGMoMTQ5LCAyOTksIDM5OSwgNDk5LCA2NDksIDc5OSwgOTk5LCAxMjQ5LCAxNDk5LCAxNzQ5LCAxOTk5LCAyNDk5LCAyOTk5LCAzNDk5KSkgJT4lIA0KICBtdXRhdGUoaW5jX21pZCA9IChpbmNfbG93K2luY19oaWdoKS8yKSAlPiUgDQogIHNlbGVjdChoaGluY3drLCBpbmNfbWlkKQ0KaGhpbmN3a19taWQgDQpgYGANCg0KRmlsdGVyIHRvIGluY2x1ZGUgb25seSBib3R0b20gNDAgcGVyIGNlbnQgb2YgaG91c2Vob2xkcyBieSBpbmNvbWUNCg0KRXF1aXZhbGlzZWQgZGlzcG9zYWJsZSBob3VzZWhvbGQgaW5jb21lIC0gUDQwID0gJDcxNCAgaW4gMjAxNS0xNiBmb3IgVklDIC0gaHR0cDovL3d3dy5hYnMuZ292LmF1L0FVU1NUQVRTL2Fic0AubnNmL0RldGFpbHNQYWdlLzY1MjMuMDIwMTUtMTY/T3BlbkRvY3VtZW50DQoNCmBgYHtyfQ0KaGhpbmN3a19taWQ0MCA8LSBoaGluY3drX21pZCAlPiUgDQogIGZpbHRlcihpbmNfbWlkIDw9IDcxNCkNCmhoaW5jd2tfbWlkNDANCmBgYA0KDQojI01pZHBvaW50cyBmb3IgcmVudCBhbmQgbW9ydGdhZ2VzDQoNCmBgYHtyfQ0KcmVudHdrX21pZCA8LSByZW50ZGF0YSAlPiUgDQogIHJlbmFtZShyZW50d2sgPSBgUk5UUkQgUmVudCAod2Vla2x5KSBSYW5nZXNgKSAlPiUgDQogIGRpc3RpbmN0KHJlbnR3aykgJT4lIA0KICBtdXRhdGUocmVudHdrID0gYXNfZmFjdG9yKHJlbnR3aykpICU+JSANCiAgZmlsdGVyKCFyZW50d2sgJWluJSBjKCdOb3Qgc3RhdGVkJywgJ05vdCBhcHBsaWNhYmxlJywgJ1RvdGFsJyApKSAlPiUgDQogIG11dGF0ZShyZW50X2xvdyA9IGMoMCwgMSwgNzUsIDEwMCwgMTI1LCAxNTAsIDE3NSwgMjAwLCAyMjUsIDI1MCwgMjc1LCAzMDAsIDMyNSwgMzUwLCAzNzUsIDQwMCwgNDI1LCA0NTAsIDU1MCwgNjUwLCA3NTAsIDg1MCwgOTUwKSkgJT4lIA0KICBtdXRhdGUocmVudF9oaWdoID0gYygwLCA3NCwgOTksIDEyNCwgMTQ5LCAxNzQsIDE5OSwgMjI0LCAyNDksIDI3NCwgMjk5LCAzMjQsIDM0OSwgMzc0LCAzOTksIDQyNCwgNDQ5LCA1NDksIDY0OSwgNzQ5LCA4NDksIDk0OSwgMTA1MCkpICU+JSANCiAgbXV0YXRlKHJlbnRfbWlkID0gKHJlbnRfbG93ICsgcmVudF9oaWdoKS8yKSAlPiUgDQogIHNlbGVjdChyZW50d2ssIHJlbnRfbWlkKQ0KcmVudHdrX21pZA0KDQptb3J0d2tfbWlkIDwtIG1vcnRkYXRhICU+JSANCiAgcmVuYW1lKG1vcnRtdGggPSBgTVJFUkQgTW9ydGdhZ2UgUmVwYXltZW50cyAobW9udGhseSkgUmFuZ2VzYCkgJT4lIA0KICBkaXN0aW5jdChtb3J0bXRoKSAlPiUgDQogIG11dGF0ZShtb3J0bXRoID0gYXNfZmFjdG9yKG1vcnRtdGgpKSAlPiUgDQogIGZpbHRlcighbW9ydG10aCAlaW4lIGMoJ05vdCBzdGF0ZWQnLCAnTm90IGFwcGxpY2FibGUnKSkgJT4lIA0KICBtdXRhdGUobW9ydF9sb3cgPSBjKDAsIDEsIDE1MCwgMzAwLCA0NTAsIDYwMCwgODAwLCAxMDAwLCAxMjAwLCAxNDAwLCAxNjAwLCAxODAwLCAyMDAwLCAyMjAwLCAyNDAwLCAyNjAwLCAzMDAwLCA0MDAwLCA1MDAwKSkgJT4lDQogIG11dGF0ZShtb3J0d2tfbG93ID0gbW9ydF9sb3cvNCkgJT4lIA0KICBtdXRhdGUobW9ydF9oaWdoID0gYygwLCAxNDksIDI5OSwgNDQ5LCA1OTksIDc5OSwgOTk5LCAxMTk5LCAxMzk5LCAxNTk5LCAxNzk5LCAxOTk5LCAyMTk5LCAyMzk5LCAyNTk5LCAyOTk5LCAzOTk5LCA0OTk5LCA1OTk5KSkgJT4lIA0KICBtdXRhdGUobW9ydHdrX2hpZ2ggPSBtb3J0X2hpZ2gvNCkgJT4lIA0KICBtdXRhdGUobW9ydF9taWQgPSAobW9ydF9sb3cgKyBtb3J0X2hpZ2gpLzIpICU+JSANCiAgbXV0YXRlKG1vcnR3a19taWQgPSAobW9ydHdrX2xvdyArIG1vcnR3a19oaWdoKS8yKSAlPiUgDQogIHNlbGVjdChtb3J0bXRoLCBtb3J0X21pZCwgbW9ydHdrX21pZCkNCm1vcnR3a19taWQgDQpgYGANCg0KIyNKb2luaW5nDQoNCmBgYHtyfQ0KI2pvaW5pbmcgdGhlIGRhdGEgICMjIyMNCnJlbnRfam9pbiA8LSBsZWZ0X2pvaW4oaGhpbmN3a19taWQ0MCwgcmVudF9oaCkNCnJlbnRfam9pbiA8LSBsZWZ0X2pvaW4ocmVudF9qb2luLCByZW50d2tfbWlkKQ0KcmVudF9qb2luDQoNCm1vcnRfam9pbiA8LSBsZWZ0X2pvaW4oaGhpbmN3a19taWQ0MCwgbW9ydF9oaCkNCm1vcnRfam9pbiA8LSBsZWZ0X2pvaW4obW9ydF9qb2luLCBtb3J0d2tfbWlkKQ0KbW9ydF9qb2luDQpgYGANCg0KIyNTdHJlc3MNCg0KYGBge3J9DQpyZW50YWxzdHJlc3MgPC0gcmVudF9qb2luICU+JSANCiAgbXV0YXRlKHByb3Bob3VzaW5nID0gcmVudF9taWQvaW5jX21pZCkgJT4lIA0KICBtdXRhdGUoaHN0cmVzcyA9IGlmZWxzZShwcm9waG91c2luZyA8PSAwLjMsIDAsIGhoKSkgJT4lIA0KICBncm91cF9ieShzYTIpICU+JSANCiAgc3VtbWFyaXNlKGxvd2luY19oaCA9IHN1bShoaCksIGhzdHJlc3MgPSBzdW0oaHN0cmVzcykpDQpyZW50YWxzdHJlc3MgPC0gbGVmdF9qb2luKHJlbnRhbHN0cmVzcywgcmVudF9kdywgYnkgPSAic2EyIikgJT4lIA0KICBzZWxlY3Qoc2EyLCBkdywgbG93aW5jX2hoLCBoc3RyZXNzKSAlPiUgDQogIG11dGF0ZShwcm9wc3RyZXNzID0gaHN0cmVzcy9kdykNCnJlbnRhbHN0cmVzcw0KDQptb3J0Z2FnZXN0cmVzcyA8LSBtb3J0X2pvaW4gJT4lIA0KICBtdXRhdGUocHJvcGhvdXNpbmcgPSBtb3J0d2tfbWlkL2luY19taWQpICU+JSANCiAgbXV0YXRlKGhzdHJlc3MgPSBpZmVsc2UocHJvcGhvdXNpbmcgPD0gMC4zLCAwLCBoaCkpICU+JSANCiAgZ3JvdXBfYnkoc2EyKSAlPiUgDQogIHN1bW1hcmlzZShsb3dpbmNfaGggPSBzdW0oaGgpLCBoc3RyZXNzID0gc3VtKGhzdHJlc3MpKQ0KbW9ydGdhZ2VzdHJlc3MgPC0gbGVmdF9qb2luKG1vcnRnYWdlc3RyZXNzLCBtb3J0X2R3LCBieSA9ICJzYTIiKSAlPiUgDQogIHNlbGVjdChzYTIsIGR3LCBsb3dpbmNfaGgsIGhzdHJlc3MpICU+JSANCiAgbXV0YXRlKHByb3BzdHJlc3MgPSBoc3RyZXNzL2R3KQ0KbW9ydGdhZ2VzdHJlc3MgDQoNCmhvdXNpbmdzdHJlc3Nfam9pbiA8LSBmdWxsX2pvaW4ocmVudGFsc3RyZXNzLCBtb3J0Z2FnZXN0cmVzcykNCmhvdXNpbmdzdHJlc3Nfc2EyIDwtIGhvdXNpbmdzdHJlc3Nfam9pbiAlPiUgDQogIGdyb3VwX2J5KHNhMikgJT4lIA0KICBzdW1tYXJpc2UoZHcgPSBzdW0oZHcpLCBsb3dpbmNfaGggPSBzdW0obG93aW5jX2hoKSwgaHN0cmVzcyA9IHN1bShoc3RyZXNzKSkgJT4lIA0KICBtdXRhdGUocHJvcF9zdHJlc3MgPSBoc3RyZXNzL2R3KSAlPiUgDQogIGZpbHRlcighaXMubmEocHJvcF9zdHJlc3MpKQ0KaG91c2luZ3N0cmVzc19zYTINCg0Kd3JpdGVfY3N2KGhvdXNpbmdzdHJlc3Nfc2EyLCAidGFibGVzX291dC9ob3VzaW5nc3RyZXNzX3NhMi5jc3YiKQ0KDQpgYGANCg0KIyNUaGUgc2hhcGVmaWxlDQoNCmBgYHtyfQ0KZ21fc2hwIDwtIHN0X3JlYWQoInNocC9TQTJfMjAxNl9HTUVMLnNocCIpICU+JSANCiAgY2xlYW5fbmFtZXMoKSAlPiUgDQogIHNlbGVjdChzYTJfbmFtZTE2KSAlPiUgDQogIGxlZnRfam9pbihob3VzaW5nc3RyZXNzX3NhMiwgYnkgPSBjKCJzYTJfbmFtZTE2IiA9ICJzYTIiKSkgJT4lIA0KICBtdXRhdGUocHJvcF9zdHJlc3MgPSByb3VuZChwcm9wX3N0cmVzcywgMikpDQpgYGANCg0KIyNUaGUgbWFwDQoNCmBgYHtyfQ0KdG1hcF9tb2RlKCJ2aWV3IikNCg0KdG1fc2hhcGUoZ21fc2hwKSArDQogIHRtX3BvbHlnb25zKCJwcm9wX3N0cmVzcyIpDQpgYGANCg0K